package com.idealighter.game.games.tongbiniuniu.manager;

import com.alibaba.fastjson.JSONObject;

import com.google.inject.Inject;
import com.google.inject.Singleton;

import com.idealighter.game.chat.manager.ChatMsgMgr;
import com.idealighter.game.core.common.Game;
import com.idealighter.game.core.constant.BoolInteger;
import com.idealighter.game.core.constant.notice.NoticeType;
import com.idealighter.game.dictionary.dic.GameNoticeDic;
import com.idealighter.game.dictionary.dic.TongbiniuniuRoomDic;
import com.idealighter.game.dictionary.dic.TongbiniuniuRoomTypeDic;
import com.idealighter.game.dictionary.domain.TongbiniuniuRoomDomain;
import com.idealighter.game.dictionary.domwrapper.GameNoticeDomainWrapper;
import com.idealighter.game.gamehall.dto.MemInfo;
import com.idealighter.game.games.common.AbstractRoom;
import com.idealighter.game.games.common.AbstractSeat;
import com.idealighter.game.games.common.AbstractTable;
import com.idealighter.game.games.common.RoomState;
import com.idealighter.game.games.common.niuniu.NiuNiuCard;
import com.idealighter.game.games.tongbiniuniu.dto.BillInfo;
import com.idealighter.game.games.tongbiniuniu.dto.RoomInfo;
import com.idealighter.game.games.tongbiniuniu.dto.RoomTypeDetailInfo;
import com.idealighter.game.games.tongbiniuniu.message.ResChipsChangeMsg;
import com.idealighter.game.games.tongbiniuniu.message.ResDealCardsMsg;
import com.idealighter.game.games.tongbiniuniu.message.ResEnterGameHallMsg;
import com.idealighter.game.games.tongbiniuniu.message.ResEnterRoomMsg;
import com.idealighter.game.games.tongbiniuniu.message.ResEnterTableMsg;
import com.idealighter.game.games.tongbiniuniu.message.ResExchangeTableMsg;
import com.idealighter.game.games.tongbiniuniu.message.ResExitRoomMsg;
import com.idealighter.game.games.tongbiniuniu.message.ResExitTableMsg;
import com.idealighter.game.games.tongbiniuniu.message.ResFastEnterTableMsg;
import com.idealighter.game.games.tongbiniuniu.message.ResGameOverMsg;
import com.idealighter.game.games.tongbiniuniu.message.ResOtherEnterTableMsg;
import com.idealighter.game.games.tongbiniuniu.message.ResReadyMsg;
import com.idealighter.game.games.tongbiniuniu.message.ResReadyOverMsg;
import com.idealighter.game.games.tongbiniuniu.message.ResShowdownMsg;
import com.idealighter.game.games.tongbiniuniu.struct.TongBiNiuNiuRoom;
import com.idealighter.game.games.tongbiniuniu.struct.TongBiNiuNiuSeat;
import com.idealighter.game.games.tongbiniuniu.struct.TongBiNiuNiuTable;
import com.idealighter.game.message.core.ResMessage;
import com.idealighter.game.notice.manager.NoticeMsgMgr;
import com.idealighter.game.player.manager.PlayerMsgWriter;
import com.idealighter.game.player.struct.Player;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * . 通比牛牛消息管理.
 * 
 * @date 2016年2月17日 上午10:46:55
 */
@Singleton
public class TongBiNiuNiuMsgMgr {

  @Inject
  private PlayerMsgWriter msgWriter;
  @Inject
  private TongBiNiuNiuDataMgr dataMgr;
  @Inject
  private TongbiniuniuRoomDic roomDic;
  @Inject
  private TongbiniuniuRoomTypeDic roomTypeDic;
  @Inject
  private NoticeMsgMgr msgMgr;
  @Inject
  private GameNoticeDic gameNoticeDic;
  @Inject
  private ChatMsgMgr chatMsgMgr;


  /**
   * 发送进入游戏大厅消息 .
   * 
   * @param player 玩家.
   */
  public void sendEnterGameHallMsg(Player player) {
    ResEnterGameHallMsg msg = new ResEnterGameHallMsg();

    Collection<TongBiNiuNiuRoom> rooms = dataMgr.rooms();
    for (TongBiNiuNiuRoom room : rooms) {
      TongbiniuniuRoomDomain roomDom = roomDic.get(room.getId().intValue());
      if (roomDom.getIsActive() != 1) {
        continue;
      }
      RoomTypeDetailInfo roomTypeDetailInfo = new RoomTypeDetailInfo();

      roomTypeDetailInfo.setType(roomDom.getType());
      roomTypeDetailInfo.setTypeName(roomTypeDic.map().get(roomDom.getType()).getName());

      RoomInfo roomInfo = new RoomInfo();
      roomInfo.setRoomId(room.getId().intValue());
      roomInfo.setName(roomDom.getName());
      roomInfo.setType(roomDom.getType());
      roomInfo.setMaxNum(roomDom.getMaxNum());
      roomInfo.setFree(roomDom.getFree());
      roomInfo.setGeneral(roomDom.getGeneral());
      roomInfo.setCrowded(roomDom.getCrowded());
      roomInfo.setLower(roomDom.getLower());
      roomInfo.setUpper(roomDom.getUpper());
      roomInfo.setProportionGold(roomDom.getProportionGold());
      roomInfo.setProportionChips(roomDom.getProportionChips());
      roomInfo.setTabble(roomDom.getTable());
      roomInfo.setMaxOne(roomDom.getMaxOne());
      roomInfo.setMinOne(roomDom.getMinOne());
      roomInfo.setAfee(roomDom.getAfee());
      roomInfo.setInType(roomDom.getInType());
      roomInfo.setPlayerNum(room.getPlayers().size());
      roomInfo.setStatus(roomStatus(room).desc);
      roomInfo.setDisplayNames(roomDom.getDisplays());
      roomInfo.setPlaceHolder(roomDom.getPlaceHolder());
      roomTypeDetailInfo.getRooms().add(roomInfo);

      msg.getRoomTypes().add(roomTypeDetailInfo);
    }

    msgWriter.writeMsg(player, msg);
  }

  /**
   * 房间状态，空闲,普通,拥挤,爆满.
   * 
   * @param room .
   * @return
   */
  private RoomState roomStatus(TongBiNiuNiuRoom room) {
    int playersNum = room.getPlayers().size();
    TongbiniuniuRoomDomain roomDom = roomDic.get(room.getId().intValue());

    if (playersNum < roomDom.getMaxNum() * roomDom.getFree() / 100) {
      return RoomState.IDLE;
    } else if (playersNum < roomDom.getMaxNum() * roomDom.getGeneral() / 100) {
      return RoomState.GENERAL;
    } else if (playersNum < roomDom.getMaxNum() * roomDom.getCrowded() / 100) {
      return RoomState.CROWD;
    } else {
      return RoomState.FULL;
    }

  }

  /**
   * 发送兑换筹码消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendChipsChangeMsg(TongBiNiuNiuSeat seat) {
    ResChipsChangeMsg msg = new ResChipsChangeMsg();
    msg.setChips(seat.getTotalChips());
    msg.setOrder(seat.getOrder());
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送进入桌子消息 .
   * 
   * @param player 玩家.
   */
  public void sendEnterRoomMsg(Player player) {
    ResEnterRoomMsg msg = new ResEnterRoomMsg();
    for (AbstractTable table : player.curRoom.tables()) {
      msg.getTables().add(table.tableInfo());
    }
    msg.setMembers(player.curRoom.memInfos());
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送进入桌子消息 .
   * 
   * @param player 玩家.
   * @param table .
   */
  public void sendEnterTableMsg(Player player, AbstractTable table) {
    ResEnterTableMsg msg = new ResEnterTableMsg();
    AbstractRoom room = table.room();
    List<MemInfo> mems = new ArrayList<>();
    for (Long playerId : table.players()) {
      mems.add(room.memInfo(playerId));
    }
    msg.setMems(mems);
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送退出房间消息 .
   * 
   * @param player 玩家.
   * @param res 0:退出成功,1:在牌桌中退出失败
   */
  public void sendExitRoomMsg(Player player, int res) {
    ResExitRoomMsg msg = new ResExitRoomMsg();
    msg.setRes(res);
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 向同桌的玩家发送该座位的玩家已经准备好 .
   * 
   * @param seat 座位信息.
   * @param res 0:成功,1:重复准备
   */
  public void sendReadyMsg(TongBiNiuNiuSeat seat, int res) {
    ResReadyMsg msg = new ResReadyMsg();
    msg.setRes(res);
    msg.setOrder(seat.getOrder());
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发牌 .
   * 
   * @param seat 座位信息.
   */
  public void sendDealCardsMsg(TongBiNiuNiuSeat seat) {
    ResDealCardsMsg msg = new ResDealCardsMsg();
    msg.setCardsType(seat.cardsType.niu);
    for (NiuNiuCard card : seat.bestCards) {
      msg.getCards().add(card.ordinal());
    }
    msgWriter.writeMsg(seat.getPlayerId(), msg);
  }

  /**
   * 发送交换牌桌位置消息 .
   * 
   * @param player 玩家.
   * @param res 0:成功,1:已经准备不能交换桌子,2:当前房间没有空位置
   */
  public void sendExchangeTableMsg(Player player, int res) {
    ResExchangeTableMsg msg = new ResExchangeTableMsg();
    msg.setRes(res);
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送退出桌子消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendExitTableMsg(TongBiNiuNiuSeat seat) {
    ResExitTableMsg msg = new ResExitTableMsg();
    msg.setOrder(seat.getOrder());
    msg.setPlayerId(seat.getPlayerId());
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送座位摊牌消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendShowdownMsg(TongBiNiuNiuSeat seat) {
    ResShowdownMsg msg = new ResShowdownMsg();
    msg.setOrder(seat.getOrder());
    seat.bestCards.forEach(card -> msg.getBestCards().add(card.ordinal()));
    msg.setCardsType(seat.cardsType.niu);
    sendTablePlayersMsg(seat.table, msg);
  }

  /**
   * 发送其他人进入桌子消息 .
   * 
   * @param seat 座位信息.
   */
  public void sendOtherEnterTableMsg(TongBiNiuNiuSeat seat) {
    ResOtherEnterTableMsg msg = new ResOtherEnterTableMsg();
    msg.setMem(seat.table.room.memInfo(seat.getPlayerId()));
    for (Long playerId : seat.table.players()) {
      if (playerId != seat.getPlayerId()) {
        msgWriter.writeMsg(playerId, msg);
      }
    }
  }

  /**
   * 向牌中的玩家发送游戏结束消息 .
   * 
   * @param table .
   * @param billInfos .
   */
  public void sendGameOver(TongBiNiuNiuTable table, List<BillInfo> billInfos) {
    ResGameOverMsg msg = new ResGameOverMsg();
    msg.setBillInfos(billInfos);
    sendTablePlayersMsg(table, msg);
  }

  /**
   * 发送快速进入结果消息 .
   * 
   * @param player 玩家.
   * @param res 0:成功,1:没有空位置
   */
  public void sendFastEnterTableMsg(Player player, int res) {
    ResFastEnterTableMsg msg = new ResFastEnterTableMsg();
    msg.setRes(res);
    msgWriter.writeMsg(player, msg);
  }

  /**
   * 发送全部准备消息 .
   * 
   * @param table .
   */
  public void sendReadyOverMsg(TongBiNiuNiuTable table) {
    ResReadyOverMsg msg = new ResReadyOverMsg();
    sendTablePlayersMsg(table, msg);
  }

  /**
   * 向同桌的玩家(包括自己)发送消息.
   * 
   * @param table .
   * @param msg .
   */
  public void sendTablePlayersMsg(TongBiNiuNiuTable table, ResMessage msg) {
    List<? extends AbstractSeat> seats = table.seats();
    for (int i = 0; i < seats.size(); i++) {
      AbstractSeat seat = seats.get(i);
      long playerId = seat.getPlayerId();
      if (playerId > 0) {
        msgWriter.writeMsg(playerId, msg);
      }
    }
  }

  /**
   * 向同房间的玩家(包括自己)发送消息.
   * 
   * @param room .
   * @param msg .
   */
  public void sendRoomPlayersMsg(TongBiNiuNiuRoom room, ResMessage msg) {
    room.getPlayers().forEach(p -> msgWriter.writeMsg(p, msg));
  }

  /**
   * 如果满足条件发送公告.
   * 
   * @param playerName . 玩家name.
   * @param cardType . 牌型 类型.
   * @param chips . 赢得筹码 .
   */
  public void sendedNotice(String playerName, int cardType, long chips) {

    for (GameNoticeDomainWrapper dom : gameNoticeDic.getGameDoms()
        .get(Game.TONGBI_NIUNIU.getType())) {
      JSONObject conditionData = dom.conditionData();
      // 公告条件牌型
      Integer conditioncardType = conditionData.getInteger("cardsType");
      // 公告条件赢得最小筹码
      Integer conditionMinChips = conditionData.getInteger("minChips");

      if (cardType == conditioncardType && chips >= conditionMinChips) {
        String sendContent = MessageFormat.format(dom.getContent(), playerName, chips);
        if (dom.getMarqueeShow() == BoolInteger.TRUE) { // 跑马灯公告
          msgMgr.sendMarqueeNoticeMsg(sendContent, NoticeType.GAME, dom.getInterval(),
              dom.getTimes(), dom.getColor());
        }

        if (dom.getChatShow() == BoolInteger.TRUE) { // 聊天公告
          chatMsgMgr.sendSysNoticeMsg(sendContent);
        }
      }
    }

  }
}
